// src/components/Upload/utils/uploader.ts
import axios from 'axios';
import  type { AxiosRequestConfig, AxiosProgressEvent } from 'axios';
import type { UploadConfig, UploadTask, ProgressCallback } from '../upload/types';
import { validateFile } from './validator';

export class Uploader {
  private options: UploadConfig;
  private queue: UploadTask[] = [];
  private activeUploads: number = 0;
  
  constructor(options: UploadConfig) {
    this.options = {
      maxParallel: 3,
      ...options
    };
  }

  /**
   * 添加上传任务
   */
  public async upload(
    file: File,
    config: Partial<UploadConfig> = {},
    onProgress?: ProgressCallback
  ): Promise<any> {
    const mergedConfig: UploadConfig = { ...this.options, ...config };
    
    // 验证文件
    const validation = await validateFile(file, {
      allowedTypes: mergedConfig.allowedTypes,
      maxSizeMB: mergedConfig.maxSizeMB,
      dimensions: mergedConfig.dimensions
    });
    
    if (!validation.valid) {
      throw new Error(validation.message);
    }
    
    // 创建上传任务
    return new Promise((resolve, reject) => {
      const task: UploadTask = { 
        file, 
        config: mergedConfig,
        resolve, 
        reject 
      };
      
      this.queue.push(task);
      this.processQueue(onProgress);
    });
  }

  /**
   * 批量上传
   */
  public async uploadAll(
    files: File[],
    config: Partial<UploadConfig> = {},
    onProgress?: ProgressCallback
  ): Promise<any[]> {
    return Promise.all(
      files.map(file => this.upload(file, config, onProgress))
    );
  }

  /**
   * 处理上传队列
   */
  private async processQueue(onProgress?: ProgressCallback): Promise<void> {
    if (this.activeUploads >= (this.options.maxParallel || 3) || this.queue.length === 0) {
      return;
    }
    
    this.activeUploads++;
    const task = this.queue.shift()!;
    
    try {
      const formData = new FormData();
      formData.append('file', task.file);
      
      const axiosConfig: AxiosRequestConfig = {
        baseURL: task.config.baseURL,
        url: task.config.endpoint,
        method: 'POST',
        data: formData,
        headers: {
          'Content-Type': 'multipart/form-data',
          ...task.config.headers
        },
        onUploadProgress: (progressEvent: AxiosProgressEvent) => {
          if (progressEvent.total) {
            const progress = Math.round((progressEvent.loaded * 100) / progressEvent.total);
            onProgress?.(progress);
          }
        }
      };
      
      const response = await axios(axiosConfig);
      task.resolve(response.data);
    } catch (error) {
      task.reject(error);
    } finally {
      this.activeUploads--;
      this.processQueue(onProgress);
    }
  }
}